<?php
/**
 * Service_Curl
 *
 * Класс Service_Curl осуществляет работу с CURL
 *
 * @author Egorov Aleksandr (slamer86@gmail.com)
 */
class Service_Curl {

  protected $connectionTimeout = 5; // Время ожидания соединения
  protected $requestTimeout = 30; // Время выполнения запроса
  protected $headers = array(); // Заголовки
  public $useSSL = false; // Использовать ли SSL
  public $status = 0; // Статус ответа
  private $alwaysArray = array('photos', 'block'); //ключи ответа, которые всегда должны быть массивами

  /**
   * Выполнение запроса через CURL
   *
   * @param string $method - Метод запроса GET / POST
   * @param string $url - Адрес запроса
   * @param array $arrParams - Массив параметров
   * @param bool $isMultipart - Флаг для передачи массивов
   * @return string - ответ сервера
   */
  public function httpRequest($method = null, $url = null, $arrParams = null, $arrayResult = true, $isMultipart = false, $onlyStatus = false) {
    if(empty($method) || empty($url)) return false;
    switch($method) {
      case 'GET':
        $resp = $this->httpGet($url, $arrParams, $onlyStatus);
        break;
      case 'POST':
        $resp = $this->httpPost($url, $arrParams, $onlyStatus, $isMultipart);
        break;
    }
    if (!empty($resp)) {
    	Service_Debug::log('httpRequest result', $resp);
    	$resp = str_replace(array('&lt;![CDATA[', ']]&gt;'), '', $resp);
    	if ($arrayResult) { // Если нужно конвертировать в массив
    		libxml_use_internal_errors(true); // Подавляем вывод ошибок
    		
    		$arrResult = json_decode(json_encode((array)  simplexml_load_string($resp)), 1);
    		
    		// конвертируем данные, которые обязательно должны быть массивами
    		$alwaysArray = & $this->alwaysArray;
    		$walk = function (&$value, $key, $walk) use (&$alwaysArray) {
				if(!is_array($value)) return;
    			if(in_array($key, $alwaysArray, true)) {
					if(count($value) && array_keys($value) !== range(0, count($value) - 1)) // проверяем, ассоциативный массив или нет. Если да, то надо сделать индексированный
					{
						$value = array($value);
					}
				}
					
				array_walk($value, $walk, $walk);
    		};
    		array_walk($arrResult, $walk, $walk);
    		
    		if (sizeof(libxml_get_errors())) { // Если есть ошибки, то возвращаем пустой результат
    			libxml_clear_errors();
    			return array();
    		}    
    		Service_Debug::log('httpRequest arrResult', $arrResult);
    		if (isset($arrResult['fault'])) {
    			$objDebug = new Debug();
					$objDebug->setFields(array('debug_name' => 'Booking fault', 'debug_text' => array('url' => $url . $this->buildHttpQueryRaw($arrParams), 'result' => $arrResult, 'script' => Service_Function::getValue('', $_SERVER, 'SCRIPT_FILENAME'), 'user_url' => Service_Function::getValue('', $_SERVER, 'REQUEST_URI'))));
					$objDebug->save();
    		}
    		if (isset($_GET['debug'])){
    			echo '<pre>';
    			print_r($arrResult);
    			echo '</pre>';
    		}
    		return $arrResult;
    	}
    	else return $resp;
    }
    else{
    	$objDebug = new Debug();
	  	$objDebug->setFields(array('debug_name' => 'Curl empty', 'debug_text' => array('url' => $url . $this->buildHttpQueryRaw($arrParams), 'script' => Service_Function::getValue('', $_SERVER, 'SCRIPT_FILENAME'))));
	  	$objDebug->save();
    	if ($arrayResult) return array();
    }
  }

  /**
   * Выполнение GET запроса
   *
   * @param string $url - Адрес запроса
   * @param array $arrParams - Массив параметров
   * @return string - Ответ сервера
   */
  protected function httpGet($url, $arrParams = null, $onlyStatus = false) {
		$url .= $this->buildHttpQueryRaw($arrParams);
		Service_Debug::log('parse URL', $url);
		//if (preg_match('#getRegionHotels#', $url)) echo $url . "\n";
		if (isset($_GET['debug'])) echo $url;
		
		
		$ch = $this->curlInit($url, $onlyStatus);
		curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.2) Gecko/20090729 Firefox/3.5.2 GTB5');
    $resp = $this->executeCurl($ch);
    $this->headers = array();
    return $resp;
  }

  /**
   * Выполнение POST запроса
   *
   * @param string $url - Адрес запроса
   * @param array $arrParams - Массив параметров
   * @param bool $isMultipart - Флаг для передачи массивов
   * @return string - ответ сервера
   */
  protected function httpPost($url, $arrParams = null, $onlyStatus = false, $isMultipart) {
    $ch = $this->curlInit($url, $onlyStatus);
    curl_setopt($ch, CURLOPT_POST, 1);
    // php's curl extension automatically sets the content type
    // based on whether the params are in string or array form
    if ($isMultipart) curl_setopt($ch, CURLOPT_POSTFIELDS, $arrParams);
    else curl_setopt($ch, CURLOPT_POSTFIELDS, $this->buildHttpQueryRaw($arrParams));
    $resp = $this->executeCurl($ch);    	
    $this->headers = array();
    return $resp;
  }

  /**
   * Строим строку параметров запроса
   *
   * @param array $arrParams - Массив параметров
   * @return string - строка запроса вида '?key=val&key2=val2'
   */
  public static function buildHttpQueryRaw($arrParams) {
  	if (!sizeof($arrParams)) return '';
    $return = '?';
    $i = 0;
    foreach($arrParams as $key => $value) {
    	if ($i++) $return .= '&';
    	$return .= $key . '=';
      if (is_array($value)) {
      	$k = 0;
      	foreach ($value as $val) {
      		if ($k++) $return .= ',';
					$return .= urlencode($val);
      	}
      }
      else $return .= urlencode($value);
    }
    return $return;
  }

  /**
   * Инициализация CURL
   *
   * @param string $url - Адрес запроса
   * @return object - Объект CURL
   */
  protected function curlInit($url, $onlyStatus) {
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $this->headers);
    curl_setopt($ch, CURLOPT_TIMEOUT, $this->requestTimeout);
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $this->connectionTimeout);
    //curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
    curl_setopt($ch, CURLOPT_ENCODING, '');
    if ($onlyStatus) {
    	curl_setopt($ch, CURLOPT_HEADER, true);
    	curl_setopt($ch, CURLOPT_NOBODY, true);
    }
    /*
    if (isset($_SERVER ['SERVER_ADDR']) && !empty($_SERVER['SERVER_ADDR']) && $_SERVER['SERVER_ADDR'] != '127.0.0.1') {
      curl_setopt($ch, CURLOPT_INTERFACE, $_SERVER ['SERVER_ADDR']);
    }
    */
    if ($this->useSSL === true) {
      curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
      curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
    }
		//curl_setopt($ch, CURLOPT_USERPWD, BOOKING_LOGIN . ':' . BOOKING_PASS);
    return $ch;
  }

  /**
   * Выполнение запроса
   *
   * @param object $ch - Объект CURL
   * @return string - Ответ сервера
   */
  protected function executeCurl($ch) {
		$resp = curl_exec($ch);
		curl_close($ch);
		if (preg_match('#HTTP/1.1 200#', $resp)) {
			$this->status = 200;
		}
		return $resp;
  }

}
?>